﻿using System;

namespace CI.Mesopotamia
{
    public class program
    {
        public static void Main(BootStrap bootstrap)
        {
            var simEnv = SimEnv.Instance;
            AppDomain.CurrentDomain.UnhandledException += AppDomainUnhandledException;
            simEnv.TraceLogger.LogDebug("App Start");
            var bootstrapResult = new BootstrapResult(false, false, string.Empty, Globals.MSRoboticEnvContract, string.Empty);

            if (Globals.BreakTime.Equals(new TimeSpan(0)))
                Globals.BreakTime = new TimeSpan(0, 60, 0);

            try
            {
                if (!string.IsNullOrEmpty(Properties.Settings.Default.LastScenario))
                {
                    bootstrapResult = new BootstrapResult(true, Properties.Settings.Default.UsingHW, Properties.Settings.Default.LastScenario, Properties.Settings.Default.ContractName, Properties.Settings.Default.ManifestName);
                    SimEnv.Instance.TraceLogger.LogWarn("Bootstrap Start Settings " + bootstrapResult);
                }

                bootstrap.ContractName = bootstrapResult.ContractName;
                bootstrap.ScenarioName = bootstrapResult.ScenarioName;
                bootstrap.ManifestName = bootstrapResult.ManifestName;
                bootstrap.UsingHW = bootstrapResult.UsingHW;

                bootstrap.ScenarioLoaded += SaveScenarioSettings;

                bootstrapResult = bootstrap.Start(Globals.BreakTime, bootstrapResult.FailureRestart);

                if (bootstrapResult.FailureRestart)
                {
                    SimEnv.Instance.TraceLogger.LogWarn("Bootstrap Result Settings" + Environment.NewLine + bootstrapResult);

                    // save current scenario
                    SaveScenarioSettings(bootstrapResult.ScenarioName, bootstrapResult.ContractName, bootstrapResult.ManifestName, bootstrapResult.UsingHW);

                    // exit with failure
                    Exit(-1);
                }
            }
            catch (PortException portException)
            {
                Exit(-2);
            }
            catch (Exception exception)
            {
                LogExceptionAndCloseTracer(simEnv, exception);
                // exit with failure
                Exit(-1);
            }

            SaveScenarioSettings(string.Empty, string.Empty, string.Empty, false);
            SimEnv.Instance.TraceLogger.LogWarn("Exiting Cleanly");
            Exit(0);
        }

        public static void Exit(int exitCode)
        {
            if (SimEnv.Instance.ForceCleanExit)
            {
                exitCode = 0;
                SaveScenarioSettings(string.Empty, string.Empty, string.Empty, false);
            }
            Environment.Exit(exitCode);
        }

        private static void SaveScenarioSettings(string scenarioName, string contractName, string manifestName, bool usingHW)
        {
            Properties.Settings.Default.LastScenario = scenarioName;
            Properties.Settings.Default.ContractName = contractName;
            Properties.Settings.Default.ManifestName = manifestName;
            Properties.Settings.Default.UsingHW = usingHW;
            Properties.Settings.Default.Save();

            SimEnv.Instance.TraceLogger.Close();
        }

        static void AppDomainUnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            SimEnv.Instance.ExceptionLogger((Exception)e.ExceptionObject);
            // exit with failure
            Exit(-1);
        }

        private static void LogExceptionAndCloseTracer(SimEnv simEnv, Exception exception)
        {
            simEnv.ExceptionLogger(exception);
            simEnv.TraceLogger.Close();
        }
    }
}
